﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Squog_1._1.Managers;

namespace Squog_1._1.Managers
{
    public enum ButtonControls { Jump, Attack, Equiped1, Equiped2 }
    public enum ThumbstickControls { Movement, Pointer }
    public enum TriggerControls { Fire, LazerEye }
    public enum Thumbsticks { Left, Right }
    public enum Triggers { Left, Right }
    public enum Direction { Left, Right, Up, Down }

    //EventHandeler for selection of a button
    public delegate void GamepadAttachedEvent(object o, GamepadChangeArgs e);
    public delegate void GamepadRemovedEvent(object o, GamepadChangeArgs e);

    //Arguments for the event handelers
    public class GamepadChangeArgs : EventArgs
    {
        public readonly int PlayerNumber;

        public GamepadChangeArgs(int PlayerNumber)
        {
            this.PlayerNumber = PlayerNumber;
        }
    }


    /// <summary>
    /// Manages the input from players. Add this to Game.Compontents!
    /// Just add this line into the Game1 constructor:
    /// Components.Add(new InputManager(this));
    /// </summary>
    public class InputManager : GameComponent
    {
        #region VARS
        public static event GamepadAttachedEvent GamepadAttachedDel;
        public static event GamepadRemovedEvent GamepadRemovedDel;

        private static Dictionary<Buttons, Keys> KeyboardMapping;

        private static GamePadState[] PrevStates;
        private static KeyboardState PrevKeyState;
        private static MouseState PrevMouseState;
        private static Vector2 PrevMouseVector;

        private static GamePadState[] CurrentStates;
        private static KeyboardState CurrentKeyState;
        private static MouseState CurrentMouseState;
        public static Vector2 CurrentMouseVector;

        private static float MouseSensitivity;

        private static bool MouseLocked;

        //Trigger Mappings
        //Left Click = Left Trigger
        //Right Clcik = Right Trigger

        //Right Joystick
        private static Keys JoyUp;
        private static Keys JoyDown;
        private static Keys JoyLeft;
        private static Keys JoyRight;

        private static Buttons[,] ButtonControl;
        private static Thumbsticks[,] ThumbstickControl;
        private static Triggers[,] TriggerControl;

        private static int[] ControllerVibrationTimes;

        private static bool useGP = false;
        public static bool UseGamePad
        {
            get { return useGP; }
            set
            {
#if XBOX
                useGP = true;
#else
                useGP = value;
#endif
            }
        }
        #endregion

        public InputManager(Game game)
            : base(game)
        { }

        public override void Initialize()
        {
            UseGamePad = false;

            PrevStates = new GamePadState[4];
            PrevStates[0] = GamePad.GetState(PlayerIndex.One);
            PrevStates[1] = GamePad.GetState(PlayerIndex.Two);
            PrevStates[2] = GamePad.GetState(PlayerIndex.Three);
            PrevStates[3] = GamePad.GetState(PlayerIndex.Four);
            CurrentStates = new GamePadState[4];
            CurrentStates[0] = GamePad.GetState(PlayerIndex.One);
            CurrentStates[1] = GamePad.GetState(PlayerIndex.Two);
            CurrentStates[2] = GamePad.GetState(PlayerIndex.Three);
            CurrentStates[3] = GamePad.GetState(PlayerIndex.Four);

            PrevKeyState = Keyboard.GetState();
            CurrentKeyState = Keyboard.GetState();
            CurrentMouseVector = new Vector2();

            ButtonControl = new Buttons[4, 4];
            ThumbstickControl = new Thumbsticks[4, 2];
            TriggerControl = new Triggers[4, 2];
            ControllerVibrationTimes = new int[4];


            MouseLocked = false;

            //KEYBOARD MAPPINGS
            KeyboardMapping = new Dictionary<Buttons, Keys>();

            ResetToDefaults();

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            //Updates all the previous and current States
            PrevKeyState = CurrentKeyState;
            PrevMouseState = CurrentMouseState;
            PrevMouseVector = CurrentMouseVector;
            for (int i = 0; i < 4; i++)
            {
                PrevStates[i] = CurrentStates[i];

                CurrentStates[i] = GamePad.GetState((PlayerIndex)i);

                ControllerVibrationTimes[i] -= gameTime.ElapsedGameTime.Milliseconds;
                if (ControllerVibrationTimes[i] <= 0)
                    GamePad.SetVibration((PlayerIndex)i, 0, 0);
            }
            CurrentKeyState = Keyboard.GetState();
            CurrentMouseState = Mouse.GetState();
            CurrentMouseVector += new Vector2((CurrentMouseState.X - (Game.Window.ClientBounds.Width / 2)) / MouseSensitivity, -(PrevMouseState.Y - (Game.Window.ClientBounds.Height / 2)) / MouseSensitivity);
            CurrentMouseVector.Normalize();

            if (MouseLocked)
                Mouse.SetPosition(Game.Window.ClientBounds.Width / 2, Game.Window.ClientBounds.Height / 2);

            //Checks the state of attached gamepads and calls the events accordingly
            for (int i = 0; i < 4; i++)
            {
                if (PrevStates[i].IsConnected && !CurrentStates[i].IsConnected)
                    GamepadRemovedDel(this, new GamepadChangeArgs(i));
                if (!PrevStates[i].IsConnected && CurrentStates[i].IsConnected)
                    GamepadAttachedDel(this, new GamepadChangeArgs(i));
            }

            //FOR DEBUGGING PURPOSES
            if (CurrentKeyState.IsKeyDown(Keys.OemTilde) && PrevKeyState.IsKeyUp(Keys.OemTilde))
                MouseLocked = !MouseLocked;

            base.Update(gameTime);
        }

        #region KEY CHANGE METHODS
        public static void ResetToDefaults()
        {
            JoyUp = Keys.W;
            JoyDown = Keys.S;
            JoyLeft = Keys.A;
            JoyRight = Keys.D;

            for (int i = 0; i < 4; i++)
            {
                ButtonControl[i, (int)ButtonControls.Jump] = Buttons.A;
                ButtonControl[i, (int)ButtonControls.Attack] = Buttons.B;
                ButtonControl[i, (int)ButtonControls.Equiped1] = Buttons.X;
                ButtonControl[i, (int)ButtonControls.Equiped2] = Buttons.Y;
            }

            for (int i = 0; i < 4; i++)
            {
                ThumbstickControl[i, (int)ThumbstickControls.Movement] = Thumbsticks.Left;
                ThumbstickControl[i, (int)ThumbstickControls.Pointer] = Thumbsticks.Right;
            }

            for (int i = 0; i < 4; i++)
            {
                TriggerControl[i, (int)TriggerControls.Fire] = Triggers.Left;
                TriggerControl[i, (int)TriggerControls.LazerEye] = Triggers.Right;
            }

            KeyboardMapping.Clear();
            KeyboardMapping.Add(Buttons.A, Keys.Q);
            KeyboardMapping.Add(Buttons.B, Keys.E);
            KeyboardMapping.Add(Buttons.X, Keys.R);
            KeyboardMapping.Add(Buttons.Y, Keys.F);

            KeyboardMapping.Add(Buttons.Back, Keys.Back);
            KeyboardMapping.Add(Buttons.Start, Keys.Enter);

            KeyboardMapping.Add(Buttons.DPadDown, Keys.K);
            KeyboardMapping.Add(Buttons.DPadUp, Keys.I);
            KeyboardMapping.Add(Buttons.DPadLeft, Keys.J);
            KeyboardMapping.Add(Buttons.DPadRight, Keys.L);

            MouseSensitivity = 100;
        }

        public static void ChangeMapping(Keys k, Buttons b)
        {
            if (KeyboardMapping.ContainsKey(b))
                KeyboardMapping.Remove(b);
            KeyboardMapping.Add(b, k);
        }
        public static void ChangeMapping(bool useWSAD)
        {
            if (useWSAD)
            {
                JoyUp = Keys.W;
                JoyDown = Keys.S;
                JoyLeft = Keys.A;
                JoyRight = Keys.D;
            }
            else
            {
                JoyUp = Keys.Up;
                JoyDown = Keys.Down;
                JoyLeft = Keys.Left;
                JoyRight = Keys.Right;
            }
        }

        public static void LockMouse()
        {
            MouseLocked = true;
        }
        public static void UnlockMouse()
        {
            MouseLocked = false;
        }
        #endregion

        #region DIRECT COMMANDS
        //Buttons

        #region KEYBOARD INPUT
        /// <summary>
        /// Uses the specified players controller to see when they release a button.
        /// </summary>
        /// <param name="B">The XBOX gamepad button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the button goes from pressed to released.</returns>
        public static bool OnRelease(Keys K, int PLayerIndex)
        {
            return PrevKeyState.IsKeyDown(K) && CurrentKeyState.IsKeyUp(K);
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a button.
        /// </summary>
        /// <param name="B">The XBOX gamepad button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the button goes from released to pressed.</returns>
        public static bool OnPress(Keys K, int PLayerIndex)
        {
            return PrevKeyState.IsKeyUp(K) && CurrentKeyState.IsKeyDown(K);
        }
        /// <summary>
        /// Uses the specified players controller to see when they hold a button.
        /// </summary>
        /// <param name="B">The XBOX gamepad button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True while the button is pressed.</returns>
        public static bool IsPressed(Keys K, int PlayerIndex)
        {
            return CurrentKeyState.IsKeyDown(K);
        }
        #endregion
        
        /// <summary>
        /// Uses the specified players controller to see when they release a button.
        /// </summary>
        /// <param name="B">The XBOX gamepad button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the button goes from pressed to released.</returns>
        public static bool OnRelease(Buttons B, int PLayerIndex)
        {
            if (UseGamePad)
            {
                return PrevStates[PLayerIndex].IsButtonDown(B) && CurrentStates[PLayerIndex].IsButtonUp(B);
            }
            else
            {
                Keys K;
                if (!KeyboardMapping.TryGetValue(B, out K))
                    return false;
                return PrevKeyState.IsKeyDown(K) && CurrentKeyState.IsKeyUp(K);
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a button.
        /// </summary>
        /// <param name="B">The XBOX gamepad button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the button goes from released to pressed.</returns>
        public static bool OnPress(Buttons B, int PLayerIndex)
        {
            if (UseGamePad)
            {
                return PrevStates[PLayerIndex].IsButtonUp(B) && CurrentStates[PLayerIndex].IsButtonDown(B);
            }
            else
            {
                Keys K;
                if (!KeyboardMapping.TryGetValue(B, out K))
                    return false;
                return PrevKeyState.IsKeyUp(K) && CurrentKeyState.IsKeyDown(K);
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they hold a button.
        /// </summary>
        /// <param name="B">The XBOX gamepad button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True while the button is pressed.</returns>
        public static bool IsPressed(Buttons B, int PlayerIndex)
        {
            if (UseGamePad)
            {
                return CurrentStates[PlayerIndex].IsButtonDown(B);
            }
            else
            {
                Keys K;
                if (!KeyboardMapping.TryGetValue(B, out K))
                    return false;
                return CurrentKeyState.IsKeyDown(K);
            }
        }

        //Triggers
        /// <summary>
        /// Uses the specified players controller to see when they release a trigger.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the trigger goes from pressed to released.</returns>
        public static bool OnRelease(Triggers b, int PlayerIndex)
        {
            switch (b)
            {
                case Triggers.Left:
                    if (UseGamePad)
                    {
                        return PrevStates[PlayerIndex].Triggers.Left > 0.3f &&
                                    CurrentStates[PlayerIndex].Triggers.Left < 0.3f;
                    }
                    else
                    {
                        return PrevMouseState.LeftButton == ButtonState.Pressed &&
                            CurrentMouseState.LeftButton == ButtonState.Released;
                    }
                case Triggers.Right:
                    if (UseGamePad)
                    {
                        return PrevStates[PlayerIndex].Triggers.Right > 0.3f &&
                            CurrentStates[PlayerIndex].Triggers.Right < 0.3f;
                    }
                    else
                    {
                        return PrevMouseState.RightButton == ButtonState.Pressed &&
                            CurrentMouseState.RightButton == ButtonState.Released;
                    }
                default:
                    return false;
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a trigger.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the trigger goes from released to pressed.</returns>
        public static bool OnPress(Triggers b, int PlayerIndex)
        {
            switch (b)
            {
                case Triggers.Left:
                    if (UseGamePad)
                    {
                        return PrevStates[PlayerIndex].Triggers.Left < 0.3f &&
                            CurrentStates[PlayerIndex].Triggers.Left > 0.3f;
                    }
                    else
                    {
                        return PrevMouseState.LeftButton == ButtonState.Released &&
                            CurrentMouseState.LeftButton == ButtonState.Pressed;
                    }
                case Triggers.Right:
                    if (UseGamePad)
                    {
                        return PrevStates[PlayerIndex].Triggers.Right < 0.3f &&
                            CurrentStates[PlayerIndex].Triggers.Right > 0.3f;
                    }
                    else
                    {
                        return PrevMouseState.RightButton == ButtonState.Released &&
                            CurrentMouseState.RightButton == ButtonState.Pressed;
                    }
                default:
                    return false;
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they hold a trigger.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True while the button is held.</returns>
        public static bool IsPressed(Triggers b, int PlayerIndex)
        {
            switch (b)
            {
                case Triggers.Left:
                    if (UseGamePad)
                    {
                        return CurrentStates[PlayerIndex].Triggers.Left > 0.3f;
                    }
                    else
                    {
                        return CurrentMouseState.LeftButton == ButtonState.Pressed;
                    }
                case Triggers.Right:
                    if (UseGamePad)
                    {
                        return CurrentStates[PlayerIndex].Triggers.Right > 0.3f;
                    }
                    else
                    {
                        return CurrentMouseState.RightButton == ButtonState.Pressed;
                    }
                default:
                    return false;
            }
        }
        /// <summary>
        /// Used to get the degree at which a trigger is pressed
        /// </summary>
        /// <param name="b">The XBOX controller trigger in question.</param>
        /// <param name="PlayerIndex">The player number</param>
        /// <returns>A number between 0.0 and 1.0</returns>
        public static float TriggerValue(Triggers b, int PlayerIndex)
        {
            switch (b)
            {
                case Triggers.Left:
                    if (UseGamePad)
                    {
                        return CurrentStates[PlayerIndex].Triggers.Left;
                    }
                    else
                    {
                        if (CurrentMouseState.LeftButton == ButtonState.Pressed)
                            return 1;
                        else
                            return 0;
                    }
                case Triggers.Right:
                    if (UseGamePad)
                    {
                        return CurrentStates[PlayerIndex].Triggers.Right;
                    }
                    else
                    {
                        if (CurrentMouseState.RightButton == ButtonState.Pressed)
                            return 1;
                        else
                            return 0;
                    }
                default:
                    return 0;
            }
        }

        //Thumbsticks
        /// <summary>
        /// Uses the specified players controller to see when they release a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True only when the thumbstick goes from pushed in a derection to released.</returns>
        public static bool OnRelease(Thumbsticks b, int PlayerIndex, Direction d)
        {
            Vector2 PrevStick;
            Vector2 CurrentStick;
            if (UseGamePad)
            {
                switch (b)
                {
                    case Thumbsticks.Left:
                        PrevStick = PrevStates[PlayerIndex].ThumbSticks.Left;
                        CurrentStick = CurrentStates[PlayerIndex].ThumbSticks.Left;
                        break;
                    case Thumbsticks.Right:
                        PrevStick = PrevStates[PlayerIndex].ThumbSticks.Right;
                        CurrentStick = CurrentStates[PlayerIndex].ThumbSticks.Right;
                        break;
                    default:
                        return false;
                }

                switch (d)
                {
                    case Direction.Left:
                        return PrevStick.X < -0.6f &&
                            CurrentStick.X > -0.6f;
                    case Direction.Right:
                        return PrevStick.X > 0.6f &&
                            CurrentStick.X < 0.6f;
                    case Direction.Down:
                        return PrevStick.Y < -0.6f &&
                            CurrentStick.Y > -0.6f;
                    case Direction.Up:
                        return PrevStick.Y > 0.6f &&
                            CurrentStick.Y < 0.6f;
                    default:
                        return false;
                }
            }

            switch (b)
            {
                case Thumbsticks.Left:
                    switch (d)
                    {
                        case Direction.Left:
                            return PrevKeyState.IsKeyDown(JoyLeft) && CurrentKeyState.IsKeyUp(JoyLeft);
                        case Direction.Right:
                            return PrevKeyState.IsKeyDown(JoyRight) && CurrentKeyState.IsKeyUp(JoyRight);
                        case Direction.Down:
                            return PrevKeyState.IsKeyDown(JoyDown) && CurrentKeyState.IsKeyUp(JoyDown);
                        case Direction.Up:
                            return PrevKeyState.IsKeyDown(JoyUp) && CurrentKeyState.IsKeyUp(JoyUp);
                        default:
                            return false;
                    }
                case Thumbsticks.Right:
                    switch (d)
                    {
                        case Direction.Left:
                            return PrevMouseVector.X < -0.6f &&
                                CurrentMouseVector.X > -0.6f;
                        case Direction.Right:
                            return PrevMouseVector.X > 0.6f &&
                                CurrentMouseVector.X < 0.6f;
                        case Direction.Down:
                            return PrevMouseVector.Y < -0.6f &&
                                CurrentMouseVector.Y > -0.6f;
                        case Direction.Up:
                            return PrevMouseVector.Y > 0.6f &&
                                CurrentMouseVector.Y < 0.6f;
                        default:
                            return false;
                    }
                default:
                    return false;
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True only when the thumbstick goes from released to pushed in a derection.</returns>
        public static bool OnPress(Thumbsticks b, int PlayerIndex, Direction d)
        {
            Vector2 PrevStick;
            Vector2 CurrentStick;

            if (UseGamePad)
            {
                switch (b)
                {
                    case Thumbsticks.Left:
                        PrevStick = PrevStates[PlayerIndex].ThumbSticks.Left;
                        CurrentStick = CurrentStates[PlayerIndex].ThumbSticks.Left;
                        break;
                    case Thumbsticks.Right:
                        PrevStick = PrevStates[PlayerIndex].ThumbSticks.Right;
                        CurrentStick = CurrentStates[PlayerIndex].ThumbSticks.Right;
                        break;
                    default:
                        return false;
                }

                switch (d)
                {
                    case Direction.Left:
                        return PrevStick.X > -0.6f &&
                            CurrentStick.X < -0.6f;
                    case Direction.Right:
                        return PrevStick.X < 0.6f &&
                            CurrentStick.X > 0.6f;
                    case Direction.Down:
                        return PrevStick.Y > -0.6f &&
                            CurrentStick.Y < -0.6f;
                    case Direction.Up:
                        return PrevStick.Y < 0.6f &&
                            CurrentStick.Y > 0.6f;
                    default:
                        return false;
                }
            }

            switch (b)
            {
                case Thumbsticks.Left:
                    switch (d)
                    {
                        case Direction.Left:
                            return PrevKeyState.IsKeyUp(JoyLeft) && CurrentKeyState.IsKeyDown(JoyLeft);
                        case Direction.Right:
                            return PrevKeyState.IsKeyUp(JoyRight) && CurrentKeyState.IsKeyDown(JoyRight);
                        case Direction.Down:
                            return PrevKeyState.IsKeyUp(JoyDown) && CurrentKeyState.IsKeyDown(JoyDown);
                        case Direction.Up:
                            return PrevKeyState.IsKeyUp(JoyUp) && CurrentKeyState.IsKeyDown(JoyUp);
                        default:
                            return false;
                    }
                case Thumbsticks.Right:
                    switch (d)
                    {
                        case Direction.Left:
                            return PrevMouseVector.X > -0.6f &&
                                CurrentMouseVector.X < -0.6f;
                        case Direction.Right:
                            return PrevMouseVector.X < 0.6f &&
                                CurrentMouseVector.X > 0.6f;
                        case Direction.Down:
                            return PrevMouseVector.Y > -0.6f &&
                                CurrentMouseVector.Y < -0.6f;
                        case Direction.Up:
                            return PrevMouseVector.Y < 0.6f &&
                                CurrentMouseVector.Y > 0.6f;
                        default:
                            return false;
                    }
                default:
                    return false;
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True while the thumbstick is pushed in a derection.</returns>
        public static bool IsPressed(Thumbsticks b, int PlayerIndex, Direction d)
        {
            Vector2 CurrentStick;

            if (UseGamePad)
            {
                switch (b)
                {
                    case Thumbsticks.Left:
                        CurrentStick = CurrentStates[PlayerIndex].ThumbSticks.Left;
                        break;
                    case Thumbsticks.Right:
                        CurrentStick = CurrentStates[PlayerIndex].ThumbSticks.Right;
                        break;
                    default:
                        return false;
                }

                switch (d)
                {
                    case Direction.Left:
                        return CurrentStick.X < -0.6f;
                    case Direction.Right:
                        return CurrentStick.X > 0.6f;
                    case Direction.Down:
                        return CurrentStick.Y < -0.6f;
                    case Direction.Up:
                        return CurrentStick.Y > 0.6f;
                    default:
                        return false;
                }
            }

            switch (b)
            {
                case Thumbsticks.Left:
                    switch (d)
                    {
                        case Direction.Left:
                            return CurrentKeyState.IsKeyDown(JoyLeft);
                        case Direction.Right:
                            return CurrentKeyState.IsKeyDown(JoyRight);
                        case Direction.Down:
                            return CurrentKeyState.IsKeyDown(JoyDown);
                        case Direction.Up:
                            return CurrentKeyState.IsKeyDown(JoyUp);
                        default:
                            return false;
                    }
                case Thumbsticks.Right:
                    switch (d)
                    {
                        case Direction.Left:
                            return CurrentMouseVector.X < -0.6f;
                        case Direction.Right:
                            return CurrentMouseVector.X > 0.6f;
                        case Direction.Down:
                            return CurrentMouseVector.Y < -0.6f;
                        case Direction.Up:
                            return CurrentMouseVector.Y > 0.6f;
                        default:
                            return false;
                    }
                default:
                    return false;
            }

        }
        /// <summary>
        /// Uses the specified players controller to see when they release a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True only when the thumbstick goes from pushed in a derection to released.</returns>
        public static bool OnRelease(Thumbsticks b, int PlayerIndex)
        {
            if (UseGamePad)
            {
                switch (b)
                {
                    case Thumbsticks.Left:
                        return (PrevStates[PlayerIndex].ThumbSticks.Left != Vector2.Zero && CurrentStates[PlayerIndex].ThumbSticks.Left == Vector2.Zero);
                    case Thumbsticks.Right:
                        return (PrevStates[PlayerIndex].ThumbSticks.Right != Vector2.Zero && CurrentStates[PlayerIndex].ThumbSticks.Right == Vector2.Zero);
                }
            }

            switch (b)
            {
                case Thumbsticks.Left:
                    return (PrevKeyState.IsKeyDown(JoyLeft) && CurrentKeyState.IsKeyUp(JoyLeft))
                    || (PrevKeyState.IsKeyDown(JoyRight) && CurrentKeyState.IsKeyUp(JoyRight))
                    || (PrevKeyState.IsKeyDown(JoyDown) && CurrentKeyState.IsKeyUp(JoyDown))
                    || (PrevKeyState.IsKeyDown(JoyUp) && CurrentKeyState.IsKeyUp(JoyUp));
                case Thumbsticks.Right:
                    return (PrevMouseVector.X < -0.6f &&
                        CurrentMouseVector.X > -0.6f)
                    || (PrevMouseVector.X > 0.6f &&
                        CurrentMouseVector.X < 0.6f)
                    || (PrevMouseVector.Y < -0.6f &&
                        CurrentMouseVector.Y > -0.6f)
                    || (PrevMouseVector.Y > 0.6f &&
                        CurrentMouseVector.Y < 0.6f);
                default:
                    return false;
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True only when the thumbstick goes from released to pushed in a derection.</returns>
        public static bool OnPress(Thumbsticks b, int PlayerIndex)
        {
            if (UseGamePad)
            {
                switch (b)
                {
                    case Thumbsticks.Left:
                        return (PrevStates[PlayerIndex].ThumbSticks.Left == Vector2.Zero && CurrentStates[PlayerIndex].ThumbSticks.Left != Vector2.Zero);
                    case Thumbsticks.Right:
                        return (PrevStates[PlayerIndex].ThumbSticks.Right == Vector2.Zero && CurrentStates[PlayerIndex].ThumbSticks.Right != Vector2.Zero);
                }
            }

            switch (b)
            {
                case Thumbsticks.Left:
                    return (PrevKeyState.IsKeyUp(JoyLeft) && CurrentKeyState.IsKeyDown(JoyLeft))
                    || (PrevKeyState.IsKeyUp(JoyRight) && CurrentKeyState.IsKeyDown(JoyRight))
                    || (PrevKeyState.IsKeyUp(JoyDown) && CurrentKeyState.IsKeyDown(JoyDown))
                    || (PrevKeyState.IsKeyUp(JoyUp) && CurrentKeyState.IsKeyDown(JoyUp));
                case Thumbsticks.Right:
                    return (PrevMouseVector.X < 0.6f &&
                        CurrentMouseVector.X > 0.6f)
                    || (PrevMouseVector.X > -0.6f &&
                        CurrentMouseVector.X < -0.6f)
                    || (PrevMouseVector.Y < 0.6f &&
                        CurrentMouseVector.Y > 0.6f)
                    || (PrevMouseVector.Y > -0.6f &&
                        CurrentMouseVector.Y < -0.6f);
                default:
                    return false;
            }
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The XBOX controller trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True while the thumbstick is pushed in a derection.</returns>
        public static bool IsPressed(Thumbsticks b, int PlayerIndex)
        {
            if (UseGamePad)
            {
                switch (b)
                {
                    case Thumbsticks.Left:
                        return CurrentStates[PlayerIndex].ThumbSticks.Left != Vector2.Zero;
                    case Thumbsticks.Right:
                        return CurrentStates[PlayerIndex].ThumbSticks.Right != Vector2.Zero;
                    default:
                        return false;
                }
            }

            switch (b)
            {
                case Thumbsticks.Left:
                    return CurrentKeyState.IsKeyDown(JoyLeft)
                    || CurrentKeyState.IsKeyDown(JoyRight)
                    || CurrentKeyState.IsKeyDown(JoyDown)
                    || CurrentKeyState.IsKeyDown(JoyUp);
                case Thumbsticks.Right:
                    return CurrentMouseVector.X < -0.6f
                    || CurrentMouseVector.X > 0.6f
                    || CurrentMouseVector.Y < -0.6f
                    || CurrentMouseVector.Y > 0.6f;
                default:
                    return false;
            }

        }
        /// <summary>
        /// Used to get the direction at which a thumbstick is pressed
        /// </summary>
        /// <param name="b">The XBOX controller thumbstick in question.</param>
        /// <param name="PlayerIndex">The player number</param>
        /// <returns>A direction vector with length less than or equal to 1.0/returns>
        public static Vector2 ThumbstickValue(Thumbsticks b, int PlayerIndex)
        {
            if (UseGamePad)
            {
                switch (b)
                {
                    case Thumbsticks.Left:
                        return CurrentStates[PlayerIndex].ThumbSticks.Left;
                    case Thumbsticks.Right:
                        return CurrentStates[PlayerIndex].ThumbSticks.Right;
                    default:
                        return Vector2.Zero;
                }
            }
            switch (b)
            {
                case Thumbsticks.Left:
                    Vector2 V = new Vector2(0, 0);
                    if (CurrentKeyState.IsKeyDown(JoyLeft))
                        V.X -= 1;
                    if (CurrentKeyState.IsKeyDown(JoyRight))
                        V.X += 1;
                    if (CurrentKeyState.IsKeyDown(JoyDown))
                        V.Y -= 1;
                    if (CurrentKeyState.IsKeyDown(JoyUp))
                        V.Y += 1;
                    if (V != Vector2.Zero)
                        V.Normalize();
                    return V;
                case Thumbsticks.Right:
                    return CurrentMouseVector;
                default:
                    return Vector2.Zero;
            }
        }
        #endregion

        #region PROGRAMMED COMMANDS
        //Buttons
        /// <summary>
        /// Uses the specified players controller to see when they release a button.
        /// </summary>
        /// <param name="B">The control button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the button goes from pressed to released.</returns>
        public static bool OnRelease(ButtonControls b, int PlayerIndex)
        {
            return OnRelease(ButtonControl[PlayerIndex, (int)b], PlayerIndex);
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a button.
        /// </summary>
        /// <param name="B">The control button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the button goes from released to pressed.</returns>
        public static bool OnPress(ButtonControls b, int PlayerIndex)
        {
            return OnPress(ButtonControl[PlayerIndex, (int)b], PlayerIndex);
        }
        /// <summary>
        /// Uses the specified players controller to see when they hold a button.
        /// </summary>
        /// <param name="B">The control button in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True while the button is held.</returns>
        public static bool IsPressed(ButtonControls b, int PlayerIndex)
        {
            return IsPressed(ButtonControl[PlayerIndex, (int)b], PlayerIndex);
        }

        //Triggers
        /// <summary>
        /// Uses the specified players controller to see when they release a trigger.
        /// </summary>
        /// <param name="B">The control trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the trigger goes from pressed to released.</returns>
        public static bool OnRelease(TriggerControls b, int PlayerIndex)
        {
            return OnRelease(TriggerControl[PlayerIndex, (int)b], PlayerIndex);
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a trigger.
        /// </summary>
        /// <param name="B">The control trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True only when the trigger goes from released to pressed.</returns>
        public static bool OnPress(TriggerControls b, int PlayerIndex)
        {
            return OnPress(TriggerControl[PlayerIndex, (int)b], PlayerIndex);
        }
        /// <summary>
        /// Uses the specified players controller to see when they hold a trigger.
        /// </summary>
        /// <param name="B">The control trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <returns>True while the button is held.</returns>
        public static bool IsPressed(TriggerControls b, int PlayerIndex)
        {
            return IsPressed(TriggerControl[PlayerIndex, (int)b], PlayerIndex);
        }
        /// <summary>
        /// Used to get the degree at which a trigger is pressed
        /// </summary>
        /// <param name="b">The control trigger in question.</param>
        /// <param name="PlayerIndex">The player number</param>
        /// <returns>A number between 0.0 and 1.0</returns>
        public static float TriggerValue(TriggerControls b, int PlayerIndex)
        {
            return TriggerValue(TriggerControl[PlayerIndex, (int)b], PlayerIndex);
        }

        //Thumbsticks
        /// <summary>
        /// Uses the specified players controller to see when they release a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The control trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True only when the thumbstick goes from pushed in a derection to released.</returns>
        public static bool OnRelease(ThumbstickControls b, int PlayerIndex, Direction d)
        {
            return OnRelease(ThumbstickControl[PlayerIndex, (int)b], PlayerIndex, d);
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The control trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True only when the thumbstick goes from released to pushed in a derection.</returns>
        public static bool OnPress(ThumbstickControls b, int PlayerIndex, Direction d)
        {
            return OnPress(ThumbstickControl[PlayerIndex, (int)b], PlayerIndex, d);
        }
        /// <summary>
        /// Uses the specified players controller to see when they press a thumbstick in a direction.
        /// </summary>
        /// <param name="B">The control trigger in question</param>
        /// <param name="PLayerIndex">Player Number</param>
        /// <param name="d">The direction in question</param>
        /// <returns>True while the thumbstick is pushed in a derection.</returns>
        public static bool IsPressed(ThumbstickControls b, int PlayerIndex, Direction d)
        {
            return IsPressed(ThumbstickControl[PlayerIndex, (int)b], PlayerIndex, d);
        }
        /// <summary>
        /// Used to get the direction at which a thumbstick is pressed
        /// </summary>
        /// <param name="b">The control thumbstick in question.</param>
        /// <param name="PlayerIndex">The player number</param>
        /// <returns>A direction vector with length less than or equal to 1.0/returns>
        public static Vector2 ThumbstickValue(ThumbstickControls b, int PlayerIndex)
        {
            return ThumbstickValue(ThumbstickControl[PlayerIndex, (int)b], PlayerIndex);
        }
        #endregion

        #region VIBRATION
        public static void VibrateFor(int Milliseconds, int PlayerIndex)
        {
            ControllerVibrationTimes[PlayerIndex] = Milliseconds;
            GamePad.SetVibration((PlayerIndex)PlayerIndex, 0.8f, 0.8f);
        }
        public static void VibrateFor(int Milliseconds, int PlayerIndex, float leftVibrate, float rightVibrate)
        {
            ControllerVibrationTimes[PlayerIndex] = Milliseconds;
            GamePad.SetVibration((PlayerIndex)PlayerIndex, leftVibrate, rightVibrate);
        }
        #endregion
    }
}
